import { Tag, Modal, Tree, Spin, message } from 'antd';
import { PlusOutlined, DownOutlined } from '@ant-design/icons';
import React, { useState, useEffect } from 'react';
import type { TreeProps } from 'antd/es/tree';
import type { ModalProps } from 'antd/es/modal';
import Styles from './index.less'
import { getInfoData } from './service';
import { CmsGroupAndTagVo, CmsTagVo } from './data'

const { CheckableTag } = Tag;

type valueType = Array<string>

interface ImgUploadProps {
    value?: valueType;
    onChange?: (value: valueType) => void;
    // 可选择标签数量
    length?: number;
    // 返回id false 返回标签名 true
    isTag?: boolean;
    // 搜索参数
    param?: {};
    // 弹出框属性
    modalProps?: ModalProps
}

const App: React.FC<ImgUploadProps> = ({
    value = [],
    param = {},
    onChange = () => { },
    isTag = false,
    length = 20,
    modalProps
}) => {

    const [tags, setTags] = useState<CmsTagVo[]>([]);    // 选择标签
    const [tagValue, setTagValue] = useState<valueType>(value)
    const [isModalOpen, setIsModalOpen] = useState<boolean>(false);     // 是否展示modal
    const [GroupList, setGroupList] = useState<CmsGroupAndTagVo[]>([])    // 分组数据
    const [tagMap, setTagMap] = useState({})

    // 加载
    const [loading, setLoading] = useState<boolean>(false)

    // 分组数据
    const [showTags, setShowTags] = useState<CmsTagVo[]>([])

    // 根据value生成已选中的标签
    const getShowSelcetTag = (tagIdMap: any, tagNameMap: any) => {
        let temp = []
        if (isTag) {
            // 标签名
            temp = value.map((item, index) => {
                // name:id缓存没命中的使用index做key
                return { guid: tagNameMap[item] || index, name: item }
            })

        } else {
            temp = value.map((item) => {
                // id:name缓存没命中的使用id做name
                return { guid: item, name: tagIdMap[item] || item }
            })
        }
        setTags(temp)
    }

    // 获取分组数据
    const getGroupData = async () => {
        try {
            setLoading(true)
            // tag id:name 缓存
            let tagIdMap = {}
            // tag name:id 缓存
            let tagNameMap = {}

            // tag groupId:tag[] 缓存
            let tagMap = {}
            // 请求数据
            let data = await getInfoData(param)

            data = data.reduce((total: any, item: any) => {

                // 检测total中是否有item中的type属性
                if (total[item.p_id]) {
                    total[item.p_id].tags.push(item);
                } else {
                    if (item.p_id != '-') {
                        const group = data.find((val: any) => val.guid == item.p_id) || { name: '分组异常' };

                        total[item.p_id] = {
                            name: group.name,
                            guid: item.p_id,
                            tags: [item],
                            chrildren: []
                        }
                    }
                }

                return total;
            }, {});
            data = Object.values(data);

            // 禁止选取非叶子节点
            const fun = (temp: any) => {
                return temp.map((item: any) => {

                    if (item?.tags?.length) {
                        item.tags.forEach(item => {
                            tagIdMap[item.guid] = item.name
                            tagNameMap[item.name] = item.guid
                        });
                    }
                    tagMap[item.guid] = item?.tags

                    return item
                })
            }

            setGroupList(fun(data))
            getShowSelcetTag(tagIdMap, tagNameMap)
            setTagMap(tagMap)
        } catch (error) {
            console.log(error);
        }
        setLoading(false)
    }

    useEffect(() => {
        getGroupData()
    }, [])

    // 展示model
    const showModal = (e: any) => {
        e.preventDefault();
        setIsModalOpen(true);
    };

    const handleCancel = () => {
        setIsModalOpen(false);
    };

    // 删除标签
    const deleteTags = (e: React.MouseEvent<HTMLElement>, data: CmsTagVo) => {
        e.preventDefault()
        // 过滤数据
        let tagValueTemp = [...tagValue].filter(item => {
            return !(isTag ? item == data.name : item == String(data.guid))
        })
        let tagsTemp = [...tags].filter(item => {
            return !(isTag ? item.name == data.name : item.guid == data.guid)
        })

        setTagValue(tagValueTemp)
        // 通知数据改变
        onChange(tagValueTemp)
        setTags(tagsTemp)
    }

    const selectTag = (data: CmsTagVo) => {
        if (length <= tags.length) {
            message.error(`最多可以选择${length}个标签`)
            return
        }
        if (isTag ? tagValue.includes(data.name) : tagValue.includes(String(data.guid))) {
            return
        }
        let tagValueTemp = [...tagValue]
        let tagsTemp = [...tags]
        // 添加选中数据
        tagValueTemp.push(String(isTag ? data.name : data.guid))
        tagsTemp.push(data)
        setTagValue(tagValueTemp)
        // 通知数据改变
        onChange(tagValueTemp)
        setTags(tagsTemp)
    }

    // 选择分组
    const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
        // 修改展示数据
        setShowTags(tagMap[selectedKeys.toString()] || [])
    };

    return (
        <>
            {tags.map(item => {
                return <Tag
                    key={item.guid}
                    className={Styles.tags}
                    closable
                    onClose={(e) => { deleteTags(e, item) }}
                >
                    {item.name}
                </Tag>
            })}
            {
                value.length < length && <Tag
                    icon={<PlusOutlined />}
                    onClick={showModal}
                    key="add"
                    className={Styles.pointer}
                >
                    添加标签
                </Tag>
            }
            <Modal
                title="标签" {...modalProps}
                width={800}
                visible={isModalOpen}
                onCancel={handleCancel}
                footer={<span>还能选择{length - tags.length}个标签</span>}
            >
                <div>

                    {/* 已选标签 */}
                    <div className={Styles.tagsSelectBox}>{tags.map(item => {
                        return <Tag
                            key={item.guid}
                            closable
                            className={Styles.tags}
                            onClose={(e) => { deleteTags(e, item) }}
                        >
                            {item.name}
                        </Tag>
                    })}</div>

                    <div className={Styles.tagsBox}>

                        <Spin spinning={loading}>
                            {/* 分组菜单 */}
                            <div className={Styles.tagsMenu}>
                                <Tree
                                    showLine
                                    switcherIcon={<DownOutlined />}
                                    onSelect={onSelect}
                                    treeData={GroupList}
                                    fieldNames={{ title: 'name', key: 'guid' }}
                                />
                            </div>
                        </Spin>

                        <div>
                            <h3>添加标签</h3>
                            {showTags.map(item => {
                                return <CheckableTag
                                    className={Styles.tags}
                                    style={{ cursor: 'pointer' }}
                                    key={item.guid}
                                    onClick={() => { selectTag(item) }}
                                    checked={isTag ? tagValue.includes(item.name) : tagValue.includes(String(item.guid))}
                                >
                                    {item.name}
                                </CheckableTag>
                            })}
                        </div>
                    </div>
                </div>
            </Modal>
        </>
    );
};

export default App;